package org.folio.rest.impl.other.reserve_station;

import io.vertx.core.Vertx;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;
import org.folio.rest.impl.other.reserve_station.model.ReserveDelayed;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

import java.util.concurrent.DelayQueue;

/**
 * 主要负责 活动报名待结束的处理, 当活动报名开始之后, 任务会提交到这个类的队列中
 * 并且同时激活一个面向用户报名的服务对象,向用户提供报名排队的服务,
 * 活动结束之后,将持久化活动报名的数据,并将该服务对象销毁
 */
public class ReserveEndPond implements Runnable {
    private final static Logger logger = LoggerFactory.getLogger("modparty");
    private static volatile DelayQueue<ReserveDelayed> queueReserve = new DelayQueue<>();
    private static ConcurrentHashMap<String, ReserveQueueService> reserveServerMap =
            new ConcurrentHashMap<>();
    private static ConcurrentHashMap<String, Boolean> reserveEndStatusMap =
            new ConcurrentHashMap<>();
    private static Vertx vertx;

    private static String tenant;

    public ReserveEndPond(Vertx vertx,String tenant){
        this.vertx = vertx;
        this.tenant = tenant;
    }

    @Override
    public void run() {
        logger.info("已激活等待活动报名结束的队列，目前共有"+queueReserve.size()+"个活动准备结束报名");
        while (true){
            try {
                ReserveDelayed result = queueReserve.take();
                //处理结束之后的相关事务
                if (result != null){
                    logger.info("活动:【"+result.getPartyId()+"】报名已结束,将报名人员持久化到数据库中，解散排队队伍！");
                  this.saveReserveData(result);

                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 添加已经开始报名并且待报名的活动
     * @param reserveDelayed
     */
    public static void addReserveDelayed(ReserveDelayed reserveDelayed){
         queueReserve.add(reserveDelayed);
         ReserveQueueService reserveQueueService = new ReserveQueueService(reserveDelayed, vertx, tenant);
         //启动队列循环
         reserveQueueService.startQueueThread();
         reserveEndStatusMap.put(reserveDelayed.getPartyId(),false);
         reserveServerMap.put(reserveDelayed.getPartyId(),reserveQueueService);
    }
    public static Boolean remove(final String partyId){
        Boolean status = reserveEndStatusMap.get(partyId);
        if (status == null || status ){
            return false;
        }
        Optional<ReserveDelayed> reserve = queueReserve.stream().filter(a -> a.getPartyId().equals(partyId)).findAny();
        if (!reserve.isPresent()){
            return false;
        }

        queueReserve.remove(reserve.get());
        reserveServerMap.remove(partyId);
        reserveEndStatusMap.remove(partyId);
        System.gc();
        return true;
    }
    //获取报名待结束的活动任务
    public static ReserveDelayed getByPartyId(final String id){
        Boolean status = reserveEndStatusMap.get(id);
        if (status == null || status){
            return null;
        }
        return queueReserve.stream().filter(a->a.getPartyId().equals(id)).findAny().get();
    }



    //获取面向用户的操作对象
    public static ReserveQueueService getReserveQueueService(String partyId){
        return reserveServerMap.get(partyId);
    }
    public static List<ReserveQueueService>  getReserveQueueServiceList(){
        List<ReserveQueueService> list = new ArrayList<>();
        reserveEndStatusMap.forEach((a,b)->{
            if (!b){
                list.add(reserveServerMap.get(a));
            }
        });
        return list;
    }
    public static void clearOutDate(){
        ConcurrentHashMap<String, Boolean> startStatusMap =
                new ConcurrentHashMap<String,Boolean>();
        reserveEndStatusMap.forEach((a,b)->{
            if (!b){
                startStatusMap.put(a, false);
            }
        });
        reserveEndStatusMap = startStatusMap;
    }

    private void saveReserveData(ReserveDelayed result){
        reserveEndStatusMap.put(result.getPartyId(),true);
        reserveServerMap.remove(result.getPartyId());
        reserveEndStatusMap.remove(result.getPartyId());
        System.gc();

    }
}
